﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;

using RexToy.UI.WinForm.ViewModel;
using RexToy.UI.WinForm.Pmlx;

namespace RexToy.UI.WinForm.Controls
{
    public abstract class ComboBoxEx : ComboBox, IDataExchange, IBindCommand
    {
        protected ComboBoxEx()
        {
            this.ValueMember = ControlConstant.ID;
            this.DisplayMember = ControlConstant.DISPLAY_NAME;

            this.SelectedIndexChanged += new EventHandler(ComboBoxEx_SelectedIndexChanged);
            this.Disposed += new EventHandler(ComboBoxEx_Disposed);
        }

        void ComboBoxEx_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (_cmd != null)
                _cmd.Execute();
        }

        void ComboBoxEx_Disposed(object sender, EventArgs e)
        {
            if (_cmd != null)
                CommandBindRegistry.Instance().RemoveItem(this);
        }

        private IUICommand _cmd;
        public IUICommand Command
        {
            get { return _cmd; }
            set
            {
                CommandBindRegistry.Instance().PutItem(this);
                _cmd = value;
            }
        }

        public void QueryCanExecute()
        {
            if (_cmd != null)
                this.Enabled = _cmd.CanExecute();
        }

        protected override void OnSelectedIndexChanged(EventArgs e)
        {
            this.UpdateModelByTrigger(UpdateModelTrigger.PropertyChanged);
            base.OnSelectedIndexChanged(e);
        }

        protected override void OnLostFocus(EventArgs e)
        {
            this.UpdateModelByTrigger(UpdateModelTrigger.LostFocus);
            base.OnLostFocus(e);
        }

        private string _bindPropertyName;
        public string BindPropertyName
        {
            get { return this.GetBindProperty(_bindPropertyName); }
            set { _bindPropertyName = value; }
        }

        private UpdateModelTrigger _updateModelTrigger;
        public UpdateModelTrigger UpdateModelTrigger
        {
            get { return _updateModelTrigger; }
            set { _updateModelTrigger = value; }
        }

        private bool _exchange;
        public bool Exchange
        {
            get { return _exchange; }
            set { _exchange = value; }
        }

        public abstract void UpdateView(ViewModelBase model);
        public abstract void UpdateModel(ViewModelBase model);

        public abstract T GetSelectedItem<T>();
        public abstract void SetSelectedItem<T>(T item);
        protected abstract object InternalGetSelectedItem();
        protected abstract void InternalSetSelectedItem(object item);

        protected Type _boundType;
        protected void BindType<T>()
        {
            Assertion.IsNull(_boundType, "Already bound to data type [{0}].", _boundType);

            _boundType = typeof(T);
        }

        protected void CheckGetSetType<T>()
        {
            Assertion.IsNotNull(_boundType, "Control not bound data yet.");
            Assertion.AreEqual(_boundType, typeof(T), "Control is bound to type [{0}], can't get/set type [{1}].", _boundType, typeof(T));
        }
    }
}
